package system

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"atools/models"
	"atools/utils"

	hook "github.com/robotn/gohook"
	"github.com/wailsapp/wails/v2/pkg/runtime"
)

// NewApp creates a new App application struct
func NewApp() *App {
	app := &App{
		WindowWidth: 800,
		CellHeight:  100,
		BaseDir:     getUserCacheDir(),
		Preferences: getDefaultPreferences(),
	}

	// 加载用户偏好设置
	app.loadPreferences()

	return app
}

func getDefaultPreferences() models.UserPreferences {
	return models.UserPreferences{
		Theme:           "system",
		HotKey:          "alt+space",
		MaxResults:      20,
		ShowInMenuBar:   true,
		LaunchAtStartup: true,
		DefaultBrowser:  "",
	}
}

func getUserCacheDir() string {
	dir, _ := os.UserHomeDir()
	baseDir := filepath.Join(dir, ".atools")
	_, err := os.Stat(baseDir)
	if err != nil {
		err = os.MkdirAll(baseDir, os.ModePerm)
		if err != nil {
			println("创建目录失败:", err.Error())
			return ""
		}
	}

	// 创建图标缓存目录
	iconDir := filepath.Join(baseDir, "app_icons")
	if _, err := os.Stat(iconDir); os.IsNotExist(err) {
		os.MkdirAll(iconDir, os.ModePerm)
	}

	return baseDir
}

// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (app *App) Startup(ctx context.Context) {
	app.Ctx = ctx
	fmt.Println("应用启动，保存上下文...")

	// 初始隐藏窗口
	fmt.Println("初始化时隐藏窗口...")
	runtime.Hide(ctx)

	// 启动热键监听
	go func() {
		fmt.Println("开始设置热键监听...")
		// 解析热键配置
		keys := parseHotKey(app.Preferences.HotKey)
		fmt.Printf("注册热键: %v (原始配置: %s)\n", keys, app.Preferences.HotKey)

		// 尝试手动触发窗口显示，测试窗口显示功能是否正常
		fmt.Println("3秒后尝试手动显示窗口...")
		time.Sleep(3 * time.Second)
		fmt.Println("手动触发窗口显示...")
		runtime.WindowShow(ctx)
		fmt.Println("手动显示窗口命令已发送")

		// 注册热键回调
		fmt.Println("注册热键回调函数...")
		hook.Register(hook.KeyDown, keys, func(e hook.Event) {
			fmt.Printf("热键触发: %v，尝试显示窗口...\n", e)
			// 确保在主线程中执行UI操作
			runtime.WindowShow(ctx)
			fmt.Println("WindowShow 调用完成")
		})

		fmt.Println("启动热键监听服务...")
		s := hook.Start()
		fmt.Println("热键监听已启动，等待事件...")
		<-hook.Process(s)
	}()

	// 定期保存使用数据
	go app.periodicDataSave()

	// 异步加载应用列表，避免阻塞启动
	go func() {
		fmt.Println("开始异步加载应用列表...")

		// 获取已安装的应用
		installedApps, err := app.GetInstalledApps()
		if err != nil {
			fmt.Printf("获取已安装应用失败: %v\n", err)
			installedApps = []models.InstalledApp{}
		}
		app.InstalledApp = installedApps

		fmt.Printf("成功加载 %d 个已安装应用\n", len(app.InstalledApp))

		// 添加自定义网页应用
		app.InstalledApp = append(app.InstalledApp, app.Preferences.CustomWebApps...)

		fmt.Printf("添加自定义应用后，总应用数: %d\n", len(app.InstalledApp))

		// 预处理应用数据，确保拼音信息正确
		app.preprocessApps()

		// 加载收藏状态
		app.loadFavoriteStatus()

		fmt.Println("应用列表加载完成！")
	}()
}

// 预处理应用数据
func (app *App) preprocessApps() {
	for i := range app.InstalledApp {
		// 确保拼音信息正确生成
		if app.InstalledApp[i].EnName == "" {
			app.InstalledApp[i].EnName = utils.GetPingYin(app.InstalledApp[i].Name)
		}
	}
}

// 加载收藏状态
func (app *App) loadFavoriteStatus() {
	favoriteMap := make(map[string]bool)
	for _, favPath := range app.Preferences.FavoriteApps {
		favoriteMap[favPath] = true
	}

	for i := range app.InstalledApp {
		app.InstalledApp[i].IsFavorite = favoriteMap[app.InstalledApp[i].Path]
	}
}

// 解析热键配置
func parseHotKey(hotkey string) []string {
	// 默认为 alt+space
	if hotkey == "" {
		return []string{"alt", "space"}
	}

	// 简单的解析逻辑，可以根据需要扩展
	parts := []string{}
	for _, part := range strings.Split(hotkey, "+") {
		part = strings.ToLower(strings.TrimSpace(part))
		// 确保键名符合 gohook 库的要求
		switch part {
		case "alt":
			parts = append(parts, "alt")
		case "ctrl", "control":
			parts = append(parts, "ctrl")
		case "shift":
			parts = append(parts, "shift")
		case "cmd", "command", "super":
			parts = append(parts, "cmd")
		case "space", "spacebar":
			parts = append(parts, "space")
		default:
			// 对于其他键，直接添加
			parts = append(parts, part)
		}
	}
	fmt.Printf("解析热键 '%s' 为: %v\n", hotkey, parts)
	return parts
}

// 定期保存数据
func (app *App) periodicDataSave() {
	ticker := time.NewTicker(5 * time.Minute)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			app.savePreferences()
		}
	}
}

// 加载用户偏好设置
func (app *App) loadPreferences() {
	if app.BaseDir == "" {
		return
	}

	prefsPath := filepath.Join(app.BaseDir, "preferences.json")
	data, err := os.ReadFile(prefsPath)
	if err != nil {
		// 如果文件不存在，使用默认设置
		if os.IsNotExist(err) {
			app.savePreferences()
		}
		return
	}

	// 解析设置
	err = json.Unmarshal(data, &app.Preferences)
	if err != nil {
		println("解析偏好设置失败:", err.Error())
	}
}

// 保存用户偏好设置
func (app *App) savePreferences() {
	if app.BaseDir == "" {
		return
	}

	prefsPath := filepath.Join(app.BaseDir, "preferences.json")
	data, err := json.MarshalIndent(app.Preferences, "", "  ")
	if err != nil {
		println("序列化偏好设置失败:", err.Error())
		return
	}

	err = os.WriteFile(prefsPath, data, 0644)
	if err != nil {
		println("保存偏好设置失败:", err.Error())
	}
}

// 更新应用使用统计
func (app *App) UpdateAppUsage(appPath string) {
	for i, installedApp := range app.InstalledApp {
		if installedApp.Path == appPath {
			app.InstalledApp[i].LastUsed = time.Now()
			app.InstalledApp[i].UseCount++
			break
		}
	}
}

// 添加自定义网页应用
func (app *App) AddCustomWebApp(name, url, iconUrl string) {
	// 创建新的网页应用
	newApp := models.InstalledApp{
		Name:    name,
		Path:    url,
		EnName:  utils.GetPingYin(name),
		AppType: "web",
		Icon:    iconUrl,
	}

	// 添加到应用列表和用户偏好
	app.InstalledApp = append(app.InstalledApp, newApp)
	app.Preferences.CustomWebApps = append(app.Preferences.CustomWebApps, newApp)

	// 保存设置
	app.savePreferences()
}

// 设置应用为收藏
func (app *App) ToggleFavorite(appPath string) bool {
	for i, installedApp := range app.InstalledApp {
		if installedApp.Path == appPath {
			// 切换收藏状态
			app.InstalledApp[i].IsFavorite = !app.InstalledApp[i].IsFavorite

			// 更新收藏列表
			if app.InstalledApp[i].IsFavorite {
				app.Preferences.FavoriteApps = append(app.Preferences.FavoriteApps, appPath)
			} else {
				// 从收藏列表中移除
				for j, favPath := range app.Preferences.FavoriteApps {
					if favPath == appPath {
						app.Preferences.FavoriteApps = append(
							app.Preferences.FavoriteApps[:j],
							app.Preferences.FavoriteApps[j+1:]...,
						)
						break
					}
				}
			}

			// 保存设置
			app.savePreferences()
			return app.InstalledApp[i].IsFavorite
		}
	}
	return false
}

// 获取收藏的应用
func (app *App) GetFavoriteApps() []models.InstalledApp {
	var favorites []models.InstalledApp

	for _, installedApp := range app.InstalledApp {
		if installedApp.IsFavorite {
			favorites = append(favorites, installedApp)
		}
	}

	return favorites
}

// 获取最近使用的应用
func (app *App) GetRecentApps(limit int) []models.InstalledApp {
	// 创建应用副本以便排序
	appsCopy := make([]models.InstalledApp, len(app.InstalledApp))
	copy(appsCopy, app.InstalledApp)

	// 按最后使用时间排序
	sort.Slice(appsCopy, func(i, j int) bool {
		return appsCopy[i].LastUsed.After(appsCopy[j].LastUsed)
	})

	// 限制返回数量
	if limit > 0 && limit < len(appsCopy) {
		return appsCopy[:limit]
	}
	return appsCopy
}

// 获取最常用的应用
func (app *App) GetMostUsedApps(limit int) []models.InstalledApp {
	// 创建应用副本以便排序
	appsCopy := make([]models.InstalledApp, len(app.InstalledApp))
	copy(appsCopy, app.InstalledApp)

	// 按使用次数排序
	sort.Slice(appsCopy, func(i, j int) bool {
		return appsCopy[i].UseCount > appsCopy[j].UseCount
	})

	// 限制返回数量
	if limit > 0 && limit < len(appsCopy) {
		return appsCopy[:limit]
	}
	return appsCopy
}

// Greet returns a greeting for the given name
func (app *App) Greet(name string) string {
	return fmt.Sprintf("Hello %s, It's show time!", name)
}

func (app *App) GetAppIcon() (string, error) {
	// 假设图标在 build/icons/icon.png
	data, err := os.ReadFile("build/appicon.png")
	if err != nil {
		return "", err
	}
	// 编码为 Base64
	return "data:image/png;base64," + base64.StdEncoding.EncodeToString(data), nil
}

// GetAppIconByPath 根据路径获取应用图标，返回 base64 编码的图片
func (app *App) GetAppIconByPath(iconPath string) (string, error) {
	if iconPath == "" {
		return app.GetAppIcon()
	}

	// 如果是网络图标，直接返回
	if strings.HasPrefix(iconPath, "http") {
		return iconPath, nil
	}

	// 如果已经是 base64 格式，直接返回
	if strings.HasPrefix(iconPath, "data:") {
		return iconPath, nil
	}

	// 处理本地图标文件
	var fullPath string
	if filepath.IsAbs(iconPath) {
		fullPath = iconPath
	} else {
		// 相对路径，基于 BaseDir
		fullPath = filepath.Join(app.BaseDir, "app_icons", iconPath)
	}

	// 检查文件是否存在
	if _, err := os.Stat(fullPath); os.IsNotExist(err) {
		// 文件不存在，返回默认图标
		return app.GetAppIcon()
	}

	// 读取文件
	data, err := os.ReadFile(fullPath)
	if err != nil {
		// 读取失败，返回默认图标
		return app.GetAppIcon()
	}

	// 根据文件扩展名确定 MIME 类型
	ext := strings.ToLower(filepath.Ext(fullPath))
	var mimeType string
	switch ext {
	case ".png":
		mimeType = "image/png"
	case ".jpg", ".jpeg":
		mimeType = "image/jpeg"
	case ".gif":
		mimeType = "image/gif"
	case ".svg":
		mimeType = "image/svg+xml"
	case ".ico":
		mimeType = "image/x-icon"
	default:
		mimeType = "image/png" // 默认为 PNG
	}

	// 编码为 Base64
	return fmt.Sprintf("data:%s;base64,%s", mimeType, base64.StdEncoding.EncodeToString(data)), nil
}

// 更新用户偏好设置
func (app *App) UpdatePreferences(preferences models.UserPreferences) error {
	// 保存旧的热键设置，以便检查是否需要更新
	oldHotKey := app.Preferences.HotKey

	// 更新设置
	app.Preferences = preferences

	// 如果热键改变，需要重新注册
	if oldHotKey != app.Preferences.HotKey {
		// 这里需要重新注册热键，但gohook库可能不支持动态更改
		// 可能需要重启应用才能生效
	}

	// 保存设置
	app.savePreferences()
	return nil
}
